package views;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
import java.util.Set;

import model.EnhancedCostEvaluator;
import model.MachineSelector;
import model.Problem;
import model.Process;
import model.Solution;
import model.SolverEnvironment;
import obsolete.MathSolverOrtLC;

import org.jgrapht.DirectedGraph;
import org.jgrapht.alg.ConnectivityInspector;
import org.jgrapht.alg.StrongConnectivityInspector;
import org.jgrapht.ext.GmlExporter;
import org.jgrapht.graph.DefaultEdge;

import solver.CollaboratingSolvers;
import solver.FlexDeluge;
import solver.GrbExtraLeanIPModelBuilder;
import solver.GrbLPModelBuilder;
import solver.GrbLeanIPModelBuilder;
import solver.HeuristicSolver;
import solver.LateAcceptanceHeuristicSolver;
import solver.MathSolver;
import solver.MathSolverGrbLC;
import solver.OrtLPModelBuilder;
import solver.Perturbator;
import solver.SelectionAgent3;
import solver.moves.MathMoveNeighborhoodXLocations;
import util.Chronograph;
import util.Importer;
import util.SolutionImporter;

import command.InsertProcessToMachineCommand;
import command.Invoker;
import command.MoveProcessToMachineCommand;
import command.RemoveProcessFromMachineCommand;

import etm.core.configuration.BasicEtmConfigurator;
import etm.core.configuration.EtmManager;
import etm.core.monitor.EtmMonitor;
import etm.core.renderer.SimpleTextRenderer;

public class MainApp {
	private static EtmMonitor monitor;
	static {
		String os_name = System.getProperty("os.name").toLowerCase();
		String os_arch = System.getProperty("os.arch").toLowerCase();
		if ((os_name.indexOf("win") >= 0) && (os_arch.indexOf("64") > 0))
			System.loadLibrary("libwin64//jnilinearsolver");
		else
			System.loadLibrary("jnilinearsolver");
	}

	private static void setup() {
		BasicEtmConfigurator.configure();
		monitor = EtmManager.getEtmMonitor();
		monitor.start();
	}

	private static void tearDown() {
		monitor.render(new SimpleTextRenderer());
		monitor.stop();
	}

	public static void main(String[] args) throws Exception {
		MainApp app = new MainApp();
		app.menu();
	}

	String[] datasets;
	String[] initial_solutions;
	List<String> new_solutions;
	Importer importer;
	Problem problem;
	SolutionImporter solutionImporter;

	@SuppressWarnings("unchecked")
	public MainApp() {
		Problem.RANDOM_SEED = 123456789L;
//		Problem.RANDOM_SEED = 29092007L;
//		Problem.RANDOM_SEED = 24061971L;
//		Problem.RANDOM_SEED = 15032009L;
//		Problem.RANDOM_SEED = 1L;
//		Problem.RANDOM_SEED = 17387928792173291L;
		datasets = new String[21];
		initial_solutions = new String[21];
		new_solutions = new ArrayList<String>();
		datasets[0] = "datasets//model_example.txt";
		datasets[1] = "datasets//model_a1_1.txt";
		datasets[2] = "datasets//model_a1_2.txt";
		datasets[3] = "datasets//model_a1_3.txt";
		datasets[4] = "datasets//model_a1_4.txt";
		datasets[5] = "datasets//model_a1_5.txt";
		datasets[6] = "datasets//model_a2_1.txt";
		datasets[7] = "datasets//model_a2_2.txt";
		datasets[8] = "datasets//model_a2_3.txt";
		datasets[9] = "datasets//model_a2_4.txt";
		datasets[10] = "datasets//model_a2_5.txt";
		datasets[11] = "datasets//model_b_1.txt";
		datasets[12] = "datasets//model_b_2.txt";
		datasets[13] = "datasets//model_b_3.txt";
		datasets[14] = "datasets//model_b_4.txt";
		datasets[15] = "datasets//model_b_5.txt";
		datasets[16] = "datasets//model_b_6.txt";
		datasets[17] = "datasets//model_b_7.txt";
		datasets[18] = "datasets//model_b_8.txt";
		datasets[19] = "datasets//model_b_9.txt";
		datasets[20] = "datasets//model_b_10.txt";
		initial_solutions[0] = "solutions//assignment_example.txt";
		initial_solutions[1] = "solutions//assignment_a1_1.txt";
		initial_solutions[2] = "solutions//assignment_a1_2.txt";
		initial_solutions[3] = "solutions//assignment_a1_3.txt";
		initial_solutions[4] = "solutions//assignment_a1_4.txt";
		initial_solutions[5] = "solutions//assignment_a1_5.txt";
		initial_solutions[6] = "solutions//assignment_a2_1.txt";
		initial_solutions[7] = "solutions//assignment_a2_2.txt";
		initial_solutions[8] = "solutions//assignment_a2_3.txt";
		initial_solutions[9] = "solutions//assignment_a2_4.txt";
		initial_solutions[10] = "solutions//assignment_a2_5.txt";
		initial_solutions[11] = "solutions//assignment_b_1.txt";
		initial_solutions[12] = "solutions//assignment_b_2.txt";
		initial_solutions[13] = "solutions//assignment_b_3.txt";
		initial_solutions[14] = "solutions//assignment_b_4.txt";
		initial_solutions[15] = "solutions//assignment_b_5.txt";
		initial_solutions[16] = "solutions//assignment_b_6.txt";
		initial_solutions[17] = "solutions//assignment_b_7.txt";
		initial_solutions[18] = "solutions//assignment_b_8.txt";
		initial_solutions[19] = "solutions//assignment_b_9.txt";
		initial_solutions[20] = "solutions//assignment_b_10.txt";
	}

	public void menu() throws Exception {
		setup();
		System.out.println("0 . Dataset Details");
		System.out.println("1 . Check feasibility of solution");
		System.out.println("2 . Find LP lower bounds");
		System.out.println("3 . Datasets details");
		System.out.println("4 . Random move of processes (###BROKEN!###)");
		System.out.println("5 . Test cost evaluator (###BROKEN!###)");
		System.out
				.println("6 . Solve full IP model (fix processes to specific machines) (###BROKEN!###)");
		System.out.println("7 . Solve full IP model");
		System.out
				.println("8 . Solve partition of the model (all processes, specific machines per process)");
		System.out
				.println("9 . Problem, initial_solution and new_solution details");
		System.out.println("10. Batch solve partitions of the model");
		System.out
				.println("11. Heuristic Solver (Late Acceptance Panayiotis Alefragis) ");
		System.out
				.println("12. Solve partition of the problem (selected processes, specific machines per process)");
		System.out
				.println("13. Batch solve partition of the problem (selected processes, specific machines per process)");
		System.out.println("14. Math Solver");
		System.out
				.println("15. Batch call Math Solver LC 500 iterations 10 processes X 10 machines");
		System.out.println("16. Solution schecker (C++)");
		System.out.println("17. Math Solver with Less Constraints");
		System.out.println("18. Math Solver Christos Valouxis (N/A)");
		System.out.println("19. Gurobi and ORTools Test ");
		System.out.println("20. Speed tests for Mathematical Solvers");
		System.out.println("21. Gurobi Solve with hot start");
		System.out
				.println("22. Gurobi Solve LP and get heuristic start solution");
		System.out
				.println("23. Analyze move from initial solution to best solution in  one step");
		System.out.println("24. Dependency graph");
		System.out.println("25. Test SelectionAgent3");
		System.out.println("26. Batch Run JAN2012");
		System.out.println("27. Perturbator");
		System.out.println("28. Test remove exams (CV)");
		System.out.println("29. Visualize best solutions");
		System.out.println("30. Test MathMoveNeighborhoodXLocations");
		System.out.print("Enter choice: ");
		Scanner in = new Scanner(System.in);
		int choice = in.nextInt();
		Chronograph chronos = new Chronograph();
		if (choice == 0) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method00(d);
		} else if (choice == 1) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method01(d);
		} else if (choice == 2) {
			method02();
		} else if (choice == 3) {
			method03();
		} else if (choice == 4) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method04(d);
		} else if (choice == 5) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method05(d);
		} else if (choice == 6) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method06(d);
		} else if (choice == 7) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method07(d);
		} else if (choice == 8) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method08(d);
		} else if (choice == 9) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method09(d);
		} else if (choice == 10) {
			method10();
		} else if (choice == 11) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method11(d);
		} else if (choice == 12) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method12(d);
		} else if (choice == 13) {
			method13();
		} else if (choice == 14) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method14(d);
		} else if (choice == 15) {
			method15();
		} else if (choice == 16) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method16(d);
		} else if (choice == 17) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method17(d);
		} else if (choice == 18) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method18(d);
		} else if (choice == 19) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method19(d);
		} else if (choice == 20) {
			method20();
		} else if (choice == 21) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method21(d);
		} else if (choice == 22) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method22(d);
		} else if (choice == 23) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method23(d);
		} else if (choice == 24) {
			method24();
		} else if (choice == 25) {
			method25();
		} else if (choice == 26) {
			method26();
		} else if (choice == 27) {
			method27();
		} else if (choice == 28) {
			method28();
		} else if (choice == 29) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method29(d);
		} else if (choice == 30) {
			displayProblems();
			System.out.print("Select dataset:");
			int d = in.nextInt();
			chronos.reset();
			method30(d);
		}
		chronos.lap();
		System.out.println("Time elapsed: " + chronos.getElapsedTimeAsString());
		in.close();
		tearDown();
	}

	public void method00(int problemno) {
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		// Solution solution1 = solutionImporter.readData();
		Solution solution2 = selectSolution(problemno);
		// problem.apiDemo(0, 0, 0, 0, 0);
		problem.printDetails();

		// for (int p_id = 0; p_id < problem.P; p_id++) {
		// System.out.println();
		// System.out
		// .printf("Load and Balance profit of lifting p%d from m%d is %,d\n",
		// p_id,
		// solution2.getMachineIdForProcessId(p_id),
		// solution2
		// .getLoadBalanceProfitInCaseProcessMovesFromMachine(p_id));
		// for (int m = 0; m < problem.M; m++) {
		// if (solution2.getMachineIdForProcessId(p_id) == m)
		// System.out
		// .printf("Load and Balance profit of p%d if put to m%d is %s\n",
		// p_id, m, "DOES NOT APPLY ALREADY THERE");
		// else {
		// long v = solution2
		// .getLoadBalanceMachineProfitInCaseProcessMovesToMachine(
		// p_id, m);
		// if (v != Long.MIN_VALUE)
		// System.out
		// .printf("Load and Balance profit of p%d if put to m%d is %,d\n",
		// p_id, m, v);
		// }
		// }
		// }
	}

	public void method01(int problemno) {
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution solution1 = solutionImporter.readData();
		Solution solution2 = selectSolution(problemno);

		System.out.println("1.#######################################");
		SolverEnvironment env = new SolverEnvironment(problem, solution1,
				solution2);
		EnhancedCostEvaluator ece = env.getFullValidator();
		ece.computeCost();
		long cost1 = ece.getNewSolutionCost();
		printFeasibilityAndCost(solution1, solution2);

		System.out.println("2.#######################################");
		Invoker invoker = new Invoker();
		MoveProcessToMachineCommand cmd = new MoveProcessToMachineCommand(ece);
		cmd.setP_id(0);
		cmd.setM_id(1);
		invoker.addCommand(cmd);
		invoker.executeLastCommand();
		ece.computeCost();
		printFeasibilityAndCost(solution1, solution2);
		long cost2 = ece.getNewSolutionCost();
		System.out.printf("Cost diff is %,d \n", cost2 - cost1);

		System.out.println("3.#######################################");
		invoker.undoLastCommand();
		ece.computeCost();
		printFeasibilityAndCost(solution1, solution2);
		long cost3 = ece.getNewSolutionCost();
		System.out.printf("Cost diff is %d\n", cost3 - cost2);
	}

	public void method02() {
		boolean[] include_dataset = new boolean[datasets.length];
		for (int i = 0; i < datasets.length; i++) {
			System.out.printf("Include dataset %s (Y/N)", datasets[i]);
			Scanner in = new Scanner(System.in);
			if (in.next().equalsIgnoreCase("Y"))
				include_dataset[i] = true;
			else
				include_dataset[i] = false;
		}
		for (int i = 0; i < datasets.length; i++) {
			if (include_dataset[i]) {
				System.out.println("#### START " + datasets[i] + "####");
				importer = new Importer(datasets[i]);
				importer.readData();
				problem = importer.getProblem();
				System.out.println(problem.getCondensedInfo());
				GrbLPModelBuilder grbLPModel;
				solutionImporter = new SolutionImporter(problem);
				solutionImporter.setSolutionFileName(initial_solutions[i]);
				Solution aSolution = solutionImporter.readData();
				SolverEnvironment env = new SolverEnvironment(problem,
						aSolution);
				grbLPModel = new GrbLPModelBuilder(problem, true, env);
				grbLPModel.setSolution(aSolution);
				grbLPModel.solveLP();
				System.out.println();
			}
		}
	}

	public void method03() {
		File dir = new File("datasets");
		FileFilter fileFilter = new FileFilter() {
			public boolean accept(File file) {
				return file.getName().endsWith(".txt");
			}
		};
		File[] filenames = dir.listFiles(fileFilter);
		Arrays.sort(filenames);
		for (File file : filenames) {
			Importer importer = new Importer(file.getAbsolutePath());
			importer.readData();
			Problem problem = importer.getProblem();
			System.out.println(file.getName());
			System.out.println(problem.getCondensedInfo());
			problem.calculateResourcesLB();
			// problem.printLocationNeighborhoodPattern();
			// problem.generateDependencyGraph();
			System.out.println();
		}
	}

	public void method04(int problemno) {
		problem.VERBOSE = true;
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution initial_solution = solutionImporter.readData();
		Solution new_solution = initial_solution.copy();
		int pn = 2;
		System.out.printf("Make a random move involving %d processes\n", pn);
		Random random = new Random(123456789L);
		HeuristicSolver solver = new HeuristicSolver(problem, initial_solution,
				new_solution);
		int[][] moves = solver.generateRandomMoves(pn);
		for (int i = 0; i < moves.length; i++)
			System.out.printf("Move process %d to machine %d\n", moves[i][0],
					moves[i][1]);
		new_solution.makeMoves(moves);
		EnhancedCostEvaluator ece = new EnhancedCostEvaluator();
		ece.setSolutionPair(initial_solution, new_solution);
		ece.computeCost();
		// ece.printFeasibilityAnalysis();
		ece.printCostAnalysis();
	}

	public void method05(int problemno) {
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution solution1 = solutionImporter.readData();
		Solution solution2 = selectSolution(problemno);
		// printFeasibilityAndCost(solution1, solution2);

		EnhancedCostEvaluator ece = new EnhancedCostEvaluator();
		ece.setSolutionPair(solution1, solution2);
		if (ece.isFeasible()) {
			System.out.println("New Solution is feasible");
			ece.computeCost();
			ece.printCostAnalysis();
		} else {
			System.out.println("New Solution is not feasible :)");
		}
	}

	public void method06(int problemno) {
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		System.out.println(problem.getCondensedInfo());

		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution initial_solution = solutionImporter.readData();
		SolverEnvironment env = new SolverEnvironment(problem, initial_solution);
		GrbLPModelBuilder grbLPModel = new GrbLPModelBuilder(problem, false,
				env);
		grbLPModel.setSolution(initial_solution);
		System.out.printf("How many machines do you want to fix?\n");

		Scanner in = new Scanner(System.in);
		int fixed_machines = in.nextInt();

		grbLPModel.solveWithFixedMachines(fixed_machines);
		Solution new_solution = grbLPModel.saveToSolution();
		saveSolution(problemno, initial_solution, new_solution);
	}

	public void method07(int problemno) {
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		System.out.println(problem.getCondensedInfo());

		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution initial_solution = solutionImporter.readData();
		Solution new_solution;
		SolverEnvironment env = new SolverEnvironment(problem, initial_solution);

		System.out.printf("Which solver 1:GRB or 2:ORTOOLS-CBC \n");
		Scanner in = new Scanner(System.in);
		int solver_type = in.nextInt();
		if (solver_type == 1) {
			GrbLPModelBuilder grbLPModel = new GrbLPModelBuilder(problem, true,
					env);
			grbLPModel.setSolution(env.getInitialSolution());
			grbLPModel.solve();
			new_solution = grbLPModel.saveToSolution();
		} else {
			OrtLPModelBuilder orToolsLPModel = new OrtLPModelBuilder(problem,
					true);
			orToolsLPModel.setSolution(initial_solution);
			orToolsLPModel.solve();
			new_solution = orToolsLPModel.saveSolution();
		}
		saveSolution(problemno, initial_solution, new_solution);
	}

	public void method08(int problemno) {
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		System.out.println(problem.getCondensedInfo());

		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution initial_solution = solutionImporter.readData();
		Solution new_solution;

		System.out
				.println("Enter number of eligible machines for each process (default=3)");
		Scanner in = new Scanner(System.in);
		int nemp = in.nextInt();
		randomlySelectMachinesPerProcess(initial_solution, nemp);

		GrbLeanIPModelBuilder grbLeanIPModelBuilder = new GrbLeanIPModelBuilder(
				problem, true);
		grbLeanIPModelBuilder.setSolution(initial_solution);
		boolean isSolved = grbLeanIPModelBuilder.solve();
		if (isSolved) {
			new_solution = grbLeanIPModelBuilder.saveToSolution();
			saveSolution(problemno, initial_solution, new_solution);
		}
	}

	public void method09(int problemno) {
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		problem.printDetails();
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution solution1 = solutionImporter.readData();
		System.out.println("INITIAL SOLUTION");
		solution1.printDetails();
		System.out.println("NEW SOLUTION");
		Solution solution2 = selectSolution(problemno);
		solution2.printDetails();
		printFeasibilityAndCost(solution1, solution2);
	}

	public void method10() {
		boolean[] include_dataset = new boolean[datasets.length];
		for (int i = 0; i < datasets.length; i++) {
			System.out.printf("Include dataset %s (Y/N)", datasets[i]);
			Scanner in = new Scanner(System.in);
			if (in.next().equalsIgnoreCase("Y"))
				include_dataset[i] = true;
			else
				include_dataset[i] = false;
		}
		for (int problemno = 0; problemno < 11; problemno++) {
			if (!include_dataset[problemno])
				continue;
			for (int nemp = 3; nemp <= 5; nemp++) {
				importer = new Importer(datasets[problemno]);
				importer.readData();
				problem = importer.getProblem();
				System.out.println(problem.getCondensedInfo());

				solutionImporter = new SolutionImporter(problem);
				solutionImporter
						.setSolutionFileName(initial_solutions[problemno]);
				Solution initial_solution = solutionImporter.readData();
				Solution new_solution;
				randomlySelectMachinesPerProcess(initial_solution, nemp);
				GrbLeanIPModelBuilder grbLeanIPModelBuilder = new GrbLeanIPModelBuilder(
						problem, true);
				grbLeanIPModelBuilder.setSolution(initial_solution);
				boolean isSolved = grbLeanIPModelBuilder.solve();
				if (isSolved) {
					new_solution = grbLeanIPModelBuilder.saveToSolution();
					saveSolution(problemno, initial_solution, new_solution);
				}
			}
		}
	}

	public void method11(int problemno) throws Exception {
		int TIME_LIMIT = 300;
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution solution1 = solutionImporter.readData();
		Problem.VERBOSE = false;
		// HeuristicSolver solver = new HeuristicSolver(problem, solution1);

//		LateAcceptanceHeuristicSolver solver = new LateAcceptanceHeuristicSolver(problem, solution1);
		 CollaboratingSolvers solver = new CollaboratingSolvers(problem, solution1);
//		 FlexDeluge solver = new FlexDeluge(problem, solution1);
		// SimulatedAnnealingSolver solver = new
		// SimulatedAnnealingSolver(problem, solution1);

		int usedTime = solver.solveWithTimeLimit(TIME_LIMIT);
		saveSolution(problemno, solution1, solver.getNewSolution(), ""
				+ usedTime + "sec_" + solver.getName());
	}

	public void method12(int problemno) {
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		System.out.println(problem.getCondensedInfo());

		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution initial_solution = solutionImporter.readData();
		// initial_solution.printDetails();
		Solution new_solution;

		System.out
				.print("Enter number of processes that will be included in the model: ");
		Scanner in = new Scanner(System.in);
		int nop = in.nextInt();
		System.out
				.print("Enter number of machines per process that will be included in the model: ");
		int nemp = in.nextInt();
		List<Integer> selectedProcesses = randomlySelectProcessesAndMachines(
				initial_solution, nop, nemp);

		// select 2 processes and 3 machines per process
		// List<Integer> selectedProcesses = randomlySelectProcessesAndMachines(
		// initial_solution, 2, 3);

		for (Integer p_id : selectedProcesses) {
			Process process = problem.getProcesses().get(p_id);
			System.out.println(process.getEligibleMachinesInfo());
		}

		GrbExtraLeanIPModelBuilder grbExtraLeanIPModelBuilder = new GrbExtraLeanIPModelBuilder(
				problem, selectedProcesses, true);
		grbExtraLeanIPModelBuilder.setInitialSolution(initial_solution);
		grbExtraLeanIPModelBuilder.setCurrentSolution(initial_solution);
		boolean saveLP = false;
		boolean isSolved = grbExtraLeanIPModelBuilder.solve(saveLP);

		if (isSolved) {
			new_solution = grbExtraLeanIPModelBuilder.saveToSolution();
			saveSolution(problemno, initial_solution, new_solution);
			printFeasibilityAndCost(initial_solution, new_solution);
			// new_solution.printDetails();
		}
	}

	public void method13() {
		boolean[] include_dataset = new boolean[datasets.length];
		for (int i = 0; i < datasets.length; i++) {
			System.out.printf("Include dataset %s (Y/N)", datasets[i]);
			Scanner in = new Scanner(System.in);
			if (in.next().equalsIgnoreCase("Y"))
				include_dataset[i] = true;
			else
				include_dataset[i] = false;
		}
		for (int problemno = 0; problemno < 11; problemno++) {
			if (!include_dataset[problemno])
				continue;
			for (int nemp = 30; nemp <= 50; nemp += 10) {
				importer = new Importer(datasets[problemno]);
				importer.readData();
				problem = importer.getProblem();
				System.out.println(problem.getCondensedInfo());

				solutionImporter = new SolutionImporter(problem);
				solutionImporter
						.setSolutionFileName(initial_solutions[problemno]);
				Solution initial_solution = solutionImporter.readData();
				Solution new_solution;

				List<Integer> selectedProcesses = randomlySelectProcessesAndMachines(
						initial_solution, 50, nemp);

				for (Integer p_id : selectedProcesses) {
					Process process = problem.getProcesses().get(p_id);
					System.out.println(process.getEligibleMachinesInfo());
				}

				GrbExtraLeanIPModelBuilder grbExtraLeanIPModelBuilder = new GrbExtraLeanIPModelBuilder(
						problem, selectedProcesses, true);
				grbExtraLeanIPModelBuilder.setInitialSolution(initial_solution);
				grbExtraLeanIPModelBuilder.setCurrentSolution(initial_solution);
				boolean saveLP = false;
				boolean isSolved = grbExtraLeanIPModelBuilder.solve(saveLP);

				if (isSolved) {
					new_solution = grbExtraLeanIPModelBuilder.saveToSolution();
					saveSolution(problemno, initial_solution, new_solution);
					// printFeasibilityAndCost(initial_solution, new_solution);
					// new_solution.printDetails();
				}
			}
		}
	}

	public void method14(int problemno) {
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		System.out.println(problem.getCondensedInfo());
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution initial_solution = solutionImporter.readData();
		MathSolver solver = new MathSolver(problem, initial_solution, 10, 10);
		solver.solve();
		saveSolution(problemno, initial_solution, solver.getCurrentSolution());
		// printFeasibilityAndCost(initial_solution,
		// solver.getCurrentSolution());
	}

	private List<Integer> randomlySelectProcessesAndMachines(
			Solution initial_solution, int nop, int noem) {
		Random random = new Random(problem.RANDOM_SEED);
		nop = nop < problem.P ? nop : problem.P;
		noem = noem < problem.M ? noem : problem.M;
		List<Integer> selectedProcesses = new ArrayList<Integer>();
		List<Integer> ballot = new ArrayList<Integer>();
		for (int p_id = 0; p_id < problem.P; p_id++) {
			ballot.add(p_id);
		}
		Collections.shuffle(ballot, random);
		for (int i = 0; i < nop; i++)
			selectedProcesses.add(ballot.get(i));

		for (Integer p_id : selectedProcesses) {
			Process proc = problem.getProcesses().get(p_id);
			ballot = new ArrayList<Integer>();
			for (int m_id = 0; m_id < problem.M; m_id++) {
				ballot.add(m_id);
			}
			Collections.shuffle(ballot, random);
			int initial_machine_id = initial_solution
					.getMachineIdForProcessId(p_id);
			proc.addEligibleMachine(initial_machine_id);
			ballot.remove(new Integer(initial_machine_id));
			for (int i = 0; i < noem - 1; i++) {
				proc.addEligibleMachine(ballot.get(i));
			}
		}
		return selectedProcesses;
	}

	public void method15() {
		boolean[] include_dataset = new boolean[datasets.length];
		for (int i = 0; i < datasets.length; i++) {
			System.out.printf("Include dataset %s (Y/N)", datasets[i]);
			Scanner in = new Scanner(System.in);
			if (in.next().equalsIgnoreCase("Y"))
				include_dataset[i] = true;
			else
				include_dataset[i] = false;
		}
		for (int problemno = 0; problemno < 11; problemno++) {
			if (!include_dataset[problemno])
				continue;
			importer = new Importer(datasets[problemno]);
			importer.readData();
			problem = importer.getProblem();
			System.out.println(problem.getCondensedInfo());
			solutionImporter = new SolutionImporter(problem);
			solutionImporter.setSolutionFileName(initial_solutions[problemno]);
			Solution initial_solution = solutionImporter.readData();
			int nop = 50;
			int noem = 25;
			int time_sec = 300;
			MathSolverGrbLC solver = new MathSolverGrbLC(problem,
					initial_solution, nop, noem);
			solver.solveWithTimeLimit(time_sec);
			Solution final_solution = solver.getCurrentSolution();
			saveSolution(problemno, initial_solution, final_solution,
					String.format("GRB_%dsec_%dpX%dm", time_sec, nop, noem));
		}
	}

	public void method16(int problemno) {
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		String new_solution_fn = selectSolutionFileName(problemno);
		try {
			String linuxWine = System.getProperty("os.name").equals("Linux") ? "wine "
					: "";
			String line;
			java.lang.Process p = Runtime.getRuntime().exec(
					linuxWine
							+ String.format("sol_ch.exe %s %s %s",
									datasets[problemno],
									initial_solutions[problemno],
									new_solution_fn));
			BufferedReader input = new BufferedReader(new InputStreamReader(
					p.getInputStream()));
			while ((line = input.readLine()) != null) {
				System.out.println(line);
			}
			input.close();
		} catch (Exception err) {
			err.printStackTrace();
		}
	}

	public void method17(int problemno) {
		int nop = 50;
		int nom = 20;
		int time_sec = 300;
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		System.out.println(problem.getCondensedInfo());
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution initial_solution = solutionImporter.readData();

		MathSolverGrbLC solver = new MathSolverGrbLC(problem, initial_solution,
				nop, nom);

		// solve performing 100 iterations and saving .lp files
		// solver.solve(100, true);
		// Solution final_solution = solver.getCurrentSolution();
		// saveSolution(problemno, initial_solution, final_solution,
		// "100i_20pX20m");

		// solve for 300sec and not saving .lp files
		solver.solveWithTimeLimit(time_sec, true);
		Solution final_solution = solver.getCurrentSolution();
		saveSolution(problemno, initial_solution, final_solution,
				String.format("%dsec_%dpX%dm", time_sec, nop, nom));
	}

	public void method18(int problemno) {
		// importer = new Importer(datasets[problemno]);
		// importer.readData();
		// problem = importer.getProblem();
		// System.out.println(problem.getCondensedInfo());
		// solutionImporter = new SolutionImporter(problem);
		// solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		// Solution initial_solution = solutionImporter.readData();
		// MathSolverLC_CG solver = new MathSolverLC_CG(problem,
		// initial_solution,
		// 10, 10);
		// try {
		// solver.solveWithTimeLimit(300);
		// } catch (GRBException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// }
		// Solution final_solution = solver.getCurrentSolution();
		// saveSolution(problemno, initial_solution, final_solution, "CV");
	}

	public void method19(int problemno) {
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		System.out.println(problem.getCondensedInfo());
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution initial_solution = solutionImporter.readData();
		System.out.println("Choose solver 1: GUROBI 2: CBC");
		Scanner in = new Scanner(System.in);
		int choice = in.nextInt();
		int nop = 30;
		int nom = 20;
		int time_sec = 300;
		if (choice == 1) {
			MathSolverGrbLC solver = new MathSolverGrbLC(problem,
					initial_solution, nop, nom);
			solver.solveWithTimeLimit(time_sec);
			Solution final_solution = solver.getCurrentSolution();
			saveSolution(problemno, initial_solution, final_solution,
					String.format("GRB_%dsec_%dpX%dm", time_sec, nop, nom));
		} else {
			MathSolverOrtLC solver = new MathSolverOrtLC(problem,
					initial_solution, nop, nom);
			solver.solveWithTimeLimit(time_sec);
			Solution final_solution = solver.getCurrentSolution();
			saveSolution(problemno, initial_solution, final_solution,
					String.format("CBC_%dsec_%dpX%dm", time_sec, nop, nom));

		}
	}

	public void method20() {
		boolean[] include_dataset = new boolean[datasets.length];
		for (int i = 0; i < datasets.length; i++) {
			System.out.printf("Include dataset %s (Y/N)", datasets[i]);
			Scanner in = new Scanner(System.in);
			if (in.next().equalsIgnoreCase("Y"))
				include_dataset[i] = true;
			else
				include_dataset[i] = false;
		}
		StringBuilder sb = new StringBuilder();
		for (int problemno = 0; problemno < 11; problemno++) {
			if (!include_dataset[problemno])
				continue;
			Chronograph chronos = new Chronograph();
			chronos.reset();
			importer = new Importer(datasets[problemno]);
			importer.readData();
			problem = importer.getProblem();
			System.out.println(problem.getCondensedInfo());
			solutionImporter = new SolutionImporter(problem);
			solutionImporter.setSolutionFileName(initial_solutions[problemno]);
			Solution initial_solution = solutionImporter.readData();
			int nop = 20;
			int noem = 10;
			int time_sec = 20;
			MathSolverGrbLC solver = new MathSolverGrbLC(problem,
					initial_solution, nop, noem);
			int rounds = solver.solveWithTimeLimit(time_sec, false);
			// Solution final_solution = solver.getCurrentSolution();
			chronos.lap();
			String s = String
					.format("GUROBI==>%s %dsec processes=%d machines=%d rounds=%d rounds_per_second=%.2f\n",
							datasets[problemno], time_sec, nop, noem, rounds,
							rounds / chronos.getElapsedTimeInSecondsAsDouble());
			System.out.println(s);
			sb.append(s);
		}
		System.out.println("############ PERFORMANCE-RESULTS#############");
		System.out.println(new Date());
		System.out.println(sb.toString());
		System.out.println("################################################");
	}

	public void method21(int problemno) {
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		System.out.println(problem.getCondensedInfo());

		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution initial_solution = solutionImporter.readData();
		Solution new_solution = selectSolution(problemno);

		System.out.printf("Which solver 1:GRB or 2:ORTOOLS-CBC \n");
		Scanner in = new Scanner(System.in);
		int solver_type = in.nextInt();
		if (solver_type == 1) {
			SolverEnvironment env = new SolverEnvironment(problem,
					initial_solution);
			GrbLPModelBuilder grbLPModel = new GrbLPModelBuilder(problem, true,
					env);
			grbLPModel.setSolution(initial_solution);
			grbLPModel.solveWithHot(new_solution);
			new_solution = grbLPModel.saveToSolution();
		} else {
			OrtLPModelBuilder orToolsLPModel = new OrtLPModelBuilder(problem,
					true);
			orToolsLPModel.setSolution(initial_solution);
			orToolsLPModel.solve();
			new_solution = orToolsLPModel.saveSolution();
		}
		saveSolution(problemno, initial_solution, new_solution);
	}

	public void method22(int problemno) {
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		System.out.println(problem.getCondensedInfo());

		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution initial_solution = solutionImporter.readData();
		Solution new_solution = null;

		System.out.printf("Which solver 1:GRB or 2:ORTOOLS-CBC \n");
		Scanner in = new Scanner(System.in);
		int solver_type = in.nextInt();
		if (solver_type == 1) {
			SolverEnvironment env = new SolverEnvironment(problem,
					initial_solution);
			GrbLPModelBuilder grbLPModel = new GrbLPModelBuilder(problem, true,
					env);
			grbLPModel.setSolution(initial_solution);
			grbLPModel.solveLP();
			new_solution = grbLPModel.getHeuristicSolution();
		} else {
			// OrtLPModelBuilder orToolsLPModel = new OrtLPModelBuilder(problem,
			// true);
			// orToolsLPModel.setSolution(initial_solution);
			// orToolsLPModel.solve();
			// new_solution = orToolsLPModel.saveSolution();
		}
		printFeasibilityAndCost(initial_solution, new_solution);
		saveSolution(problemno, initial_solution, new_solution);
	}

	public void method23(int problemno) {
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		problem.printDetails();
		problem.createOrderedByResourcesArrays();
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution solution1 = solutionImporter.readData();
		System.out.println("INITIAL SOLUTION");
		System.out.println("NEW SOLUTION");
		Solution solution2 = selectSolution(problemno);
		printFeasibilityAndCost(solution1, solution2);
		compareSolutions(solution1, solution2);
	}

	public void method24() {
		int dataset_id = 9;
		Importer importer = new Importer(datasets[dataset_id]);
		importer.readData();
		Problem problem = importer.getProblem();
		System.out.println(datasets[dataset_id]);
		System.out.println(problem.getCondensedInfo());
		problem.generateDependencyGraph();
		DirectedGraph<String, DefaultEdge> directedGraph = problem
				.getDirectedGraph();
		ConnectivityInspector<String, DefaultEdge> ci = new ConnectivityInspector<String, DefaultEdge>(
				directedGraph);
		System.out.println("Connected sets");
		for (String s : directedGraph.vertexSet()) {
			System.out.printf("%s-->%s\n", s, ci.connectedSetOf(s));
		}

		System.out.println("Strongly connected sets");
		StrongConnectivityInspector<String, DefaultEdge> sci = new StrongConnectivityInspector<String, DefaultEdge>(
				directedGraph);

		for (Set aSet : sci.stronglyConnectedSets()) {
			System.out.println(aSet);
		}

		java.io.Writer writer;

		GmlExporter<String, DefaultEdge> ge = new GmlExporter<String, DefaultEdge>();
		ge.setPrintLabels(GmlExporter.PRINT_VERTEX_LABELS);
		try {
			writer = new FileWriter(String.format("test%d.gml", dataset_id));
			ge.export(writer, directedGraph);
		} catch (IOException e) {
			e.printStackTrace();
		}

		// VertexNameProvider<String> snp = new StringNameProvider<String>();
		// EdgeNameProvider<DefaultEdge> senp = new
		// StringEdgeNameProvider<DefaultEdge>();
		// GraphMLExporter<String, DefaultEdge> gme = new
		// GraphMLExporter<String, DefaultEdge>(
		// snp, snp, senp, senp);
		// try {
		// writer = new FileWriter(String.format("test%d.graphml", dataset_id));
		// gme.export(writer, directedGraph);
		// } catch (IOException e) {
		// e.printStackTrace();
		// } catch (TransformerConfigurationException e) {
		// e.printStackTrace();
		// } catch (SAXException e) {
		// e.printStackTrace();
		// }

		// DOTExporter<String, DefaultEdge> de = new DOTExporter<String,
		// DefaultEdge>();
		// try {
		// writer = new FileWriter(String.format("test%d.dot", dataset_id));
		// de.export(writer, directedGraph);
		// } catch (IOException e) {
		// e.printStackTrace();
		// }
	}

	public void method25() {
		int problemno = 2;
		Importer importer = new Importer(datasets[problemno]);
		importer.readData();
		Problem problem = importer.getProblem();
		System.out.println(datasets[problemno]);
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution initial_solution = solutionImporter.readData();
		solutionImporter
				.setSolutionFileName("solutions//assignment_a1_2_777931649[JAN2012_300sec_LateAcceptanceHeuristicSolver].txt");
		Solution current_solution = solutionImporter.readData();
		System.out.println(problem.getCondensedInfo());
		SolverEnvironment env = new SolverEnvironment(problem,
				initial_solution, current_solution);
		SelectionAgent3 sa3 = new SelectionAgent3(env);
		sa3.selectProcessesAndMachinesBucket();

		// sa3.selectProcessesAndMachinesBasedOnOneProcessMove(40, 30);
		// sa3.selectProcessesAndMachinesBasedOnTwoProcessesAndThreeMachinesMove(
		// 40, 30);
		// sa3.selectProcessesAndMachinesBasedOnTwoProcessesExchangeMove(40,
		// 30);
		// List<Integer> selectedProcesses = sa3.getSelectedProcesses();
		// OrtExtraLeanIPModelBuilder modelBuilder = new
		// OrtExtraLeanIPModelBuilder(
		// problem, selectedProcesses, false, 5, Long.MAX_VALUE);
		// modelBuilder.setInitialSolution(initial_solution);
		// modelBuilder.setCurrentSolution(current_solution);
		// modelBuilder.includeConflictHardConstraints(true);
		// env.getFullValidator().computeCost();
		// System.out.printf("initial solution:%,d current solution:%,d\n", env
		// .getFullValidator().getInitialSolutionCost(), env
		// .getFullValidator().getNewSolutionCost());
		// long current_cost = env.getFullValidator().getNewSolutionCost();
		// boolean solved = modelBuilder.solve(true);
		// if (solved) {
		// Solution potentialSolution = modelBuilder.saveToSolution();
		// env.getFullValidator().setSolutionPair(initial_solution,
		// potentialSolution);
		// env.getFullValidator().computeCost();
		// long potential_solution_cost = env.getFullValidator()
		// .getNewSolutionCost();
		// if (env.getFullValidator().isFeasible()) {
		// System.out.printf(
		// ":) BETTER solution found %,d better (%,d)\n",
		// potential_solution_cost, current_cost
		// - potential_solution_cost);
		// }
		// current_solution.printSimilarityInfoWith(potentialSolution);
		// }
	}

	public void method26() throws Exception {
		int TIME_LIMIT = 300;
		int[] problems = { 2, 3, 4, 5, 6, 7, 8, 9, 10 };
		// int[] problems = { 10 };
		// int[] problems = { 5, 6, 7 };
		for (Integer problemno : problems) {
			// Problem.RANDOM_SEED = 1940L;
			importer = new Importer(datasets[problemno]);
			importer.readData();
			problem = importer.getProblem();
			solutionImporter = new SolutionImporter(problem);
			solutionImporter.setSolutionFileName(initial_solutions[problemno]);
			Solution solution1 = solutionImporter.readData();
			// HeuristicSolver solver = new HeuristicSolver(problem, solution1);

			LateAcceptanceHeuristicSolver solver = new LateAcceptanceHeuristicSolver(
					problem, solution1);

			// FlexDeluge solver = new FlexDeluge(problem, solution1);
			// SimulatedAnnealingSolver solver = new
			// SimulatedAnnealingSolver(problem, solution1);

			int usedTime = solver.solveWithTimeLimit(TIME_LIMIT);
			saveSolution(problemno, solution1, solver.getNewSolution(),
					"JAN2012_" + usedTime + "sec_" + solver.getName());
		}
	}

	public void method27() {
		int problemno = 2;
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution solution1 = solutionImporter.readData();
		solutionImporter
				.setSolutionFileName("solutions//assignment_a1_2_777931649[JAN2012_300sec_LateAcceptanceHeuristicSolver].txt");
		Solution solution2 = solutionImporter.readData();
		SolverEnvironment env = new SolverEnvironment(problem, solution1,
				solution2);
		Perturbator perturbator = new Perturbator(env);
		System.out.println("Perturbation");
		perturbator.moveToInferiorSolution(Long.MAX_VALUE);
		printFeasibilityAndCost(env, perturbator.getPotentialSolution());

	}

	public void method28() {
		int problemno = 2;
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution solution1 = solutionImporter.readData();
		solutionImporter
				.setSolutionFileName("solutions//assignment_a1_2_777931649[JAN2012_300sec_LateAcceptanceHeuristicSolver].txt");
		Solution solution2 = solutionImporter.readData();
		SolverEnvironment env = new SolverEnvironment(problem, solution1,
				solution2);
		EnhancedCostEvaluator ece = new EnhancedCostEvaluator(env);
		Invoker invoker = new Invoker();
		int[] selected_processes = { 10, 20, 30, 40 };
		int[] old_positions = new int[selected_processes.length];
		for (int i = 0; i < selected_processes.length; i++) {
			RemoveProcessFromMachineCommand cmd = new RemoveProcessFromMachineCommand(
					ece);
			int p = selected_processes[i];
			old_positions[i] = ece.getNewSolution().getMachineIdForProcessId(p);
			cmd.setP_id(p);
			invoker.addCommand(cmd);
			invoker.executeLastCommand();
			ece.computeCost();
			System.out.printf("Cost = %,d Unscheduled processes = %s\n",
					ece.getNewSolutionCost(), ece.getUnscheduledProcesses());
		}
		System.out.println();
		for (int i = 0; i < selected_processes.length; i++) {
			InsertProcessToMachineCommand cmd = new InsertProcessToMachineCommand(
					ece);
			int p = selected_processes[i];
			int m = old_positions[i];
			cmd.setP_id(p);
			cmd.setM_id(m);
			invoker.addCommand(cmd);
			invoker.executeLastCommand();
			ece.computeCost();
			System.out.printf("Cost = %,d Unscheduled processes = %s\n",
					ece.getNewSolutionCost(), ece.getUnscheduledProcesses());
		}

	}

	public void method29(int problemno) {
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution solution1 = solutionImporter.readData();
		Solution solution2 = selectBestSolution(problemno);
		solution2.refreshLoadCostContribution();
		solution2.refreshBalanceCostContribution();
		VisualizeJFrame app = new VisualizeJFrame(problem, solution1,
				solution2, 0L);
	}

	public void method30(int problemno) {
		importer = new Importer(datasets[problemno]);
		importer.readData();
		problem = importer.getProblem();
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName(initial_solutions[problemno]);
		Solution solution1 = solutionImporter.readData();
		Solution solution2 = solution1.copy();
		solution2.refreshLoadCostContribution();
		solution2.refreshBalanceCostContribution();
		SolverEnvironment env = new SolverEnvironment(problem, solution1,
				solution2);
		problem.computeTransientResourcesRemainingCapacityPerMachine(env);
		MathMoveNeighborhoodXLocations mmnxl = new MathMoveNeighborhoodXLocations(env,new MachineSelector(env));
		mmnxl.setSelectedNeighborhood(env.getRandom().nextInt(env.getProblem().N));
		mmnxl.performMove();
	}
	
	private void compareSolutions(Solution initial_solution,
			Solution new_solution) {
		List<Integer> diff_processes = new ArrayList<Integer>();
		for (int i = 0; i < problem.P; i++) {
			if (initial_solution.getMachineIdForProcessId(i) != new_solution
					.getMachineIdForProcessId(i)) {
				diff_processes.add(i);
			}
		}
		System.out.printf("MOVED PROCESSES %d %s\n", diff_processes.size(),
				diff_processes);
		for (Integer p_id : diff_processes) {
			Process aProcess = problem.getProcesses().get(p_id);
			aProcess.clearEligibleMachines();
			aProcess.addEligibleMachine(initial_solution
					.getMachineIdForProcessId(p_id));
			aProcess.addEligibleMachine(new_solution
					.getMachineIdForProcessId(p_id));
		}
		long cutoff = Long.MAX_VALUE;
		// OrtExtraLeanIPModelBuilder modelBuilder = new
		// OrtExtraLeanIPModelBuilder(
		// problem, diff_processes, false, 100, cutoff);
		// modelBuilder.createLP = false;
		GrbExtraLeanIPModelBuilder modelBuilder = new GrbExtraLeanIPModelBuilder(
				problem, diff_processes, false, 100, cutoff);
		modelBuilder.setInitialSolution(initial_solution);
		Solution current_solution = initial_solution.copy();
		modelBuilder.setCurrentSolution(current_solution);
		boolean solved = modelBuilder.solve(false);
		System.out.println("Solving...");
		if (solved) {
			current_solution = modelBuilder.saveToSolution();
		} else {
			System.out.println("Unable to make the complex move");
		}
		printFeasibilityAndCost(initial_solution, current_solution);
	}

	private void randomlySelectMachinesPerProcess(Solution initial_solution,
			int noem) {
		Random random = new Random(Problem.RANDOM_SEED);
		noem = noem < problem.M ? noem : problem.M;
		for (int p = 0; p < problem.P; p++) {
			Process proc = problem.getProcesses().get(p);
			List<Integer> ballot = new ArrayList<Integer>();
			for (int m_id = 0; m_id < problem.M; m_id++) {
				ballot.add(m_id);
			}
			Collections.shuffle(ballot, random);
			int initial_machine_id = initial_solution
					.getMachineIdForProcessId(p);
			proc.addEligibleMachine(initial_machine_id);
			ballot.remove(new Integer(initial_machine_id));
			for (int i = 0; i < noem - 1; i++) {
				proc.addEligibleMachine(ballot.get(i));
			}
		}
	}

	private void saveSolution(int problemno, Solution initial_solution,
			Solution new_solution, String time_limit) {
		SolverEnvironment env = new SolverEnvironment(problem,
				initial_solution, new_solution);
		EnhancedCostEvaluator ece = env.getFullValidator();
		ece.computeCost();
		// ece.printCostAnalysis();
		boolean f = ece.isFeasible();
		String sol_filename = initial_solutions[problemno].replaceAll("\\.txt",
				"");
		String fn = String.format("%s_%s%s[%s].txt", sol_filename,
				ece.getNewSolutionCost(), f ? "" : "_inf", time_limit);
		new_solution.exportToFileName(fn);
		System.out.println("File " + fn + " saved!");
	}

	String selectedDataset;

	private void saveSolution(int problemno, Solution initial_solution,
			Solution new_solution) {
		saveSolution(problemno, initial_solution, new_solution, "");
	}

	private Solution selectSolution(int problemno) {
		selectedDataset = datasets[problemno];
		String s[] = selectedDataset.split("\\.");
		final String fn = s[0].substring(10)
				.replaceFirst("model", "assignment");
		File directory = new File("solutions");
		File[] files = directory.listFiles(new FileFilter() {
			public boolean accept(File file) {
				if (file.getName().startsWith(fn)
						&& file.getName().endsWith(".txt"))
					return true;
				else
					return false;
			}
		});
		if (files.length == 0) {
			System.out.println("No files found. Bye");
			System.exit(0);
		}
		int index = 1;
		for (File f : files) {
			System.out.printf("%d. %s\n", index, f.getName());
			index++;
		}
		System.out.printf("Select solution [1-%d]:", files.length);
		Scanner in = new Scanner(System.in);
		int choice = in.nextInt();
		SolutionImporter solutionImporter2 = new SolutionImporter(problem);
		solutionImporter2.setSolutionFileName(files[choice - 1]
				.getAbsolutePath());
		Solution solution = solutionImporter2.readData();
		System.out.println();
		return solution;
	}

	private String selectSolutionFileName(int problemno) {
		selectedDataset = datasets[problemno];
		String s[] = selectedDataset.split("\\.");
		final String fn = s[0].substring(10)
				.replaceFirst("model", "assignment");
		File directory = new File("solutions");
		File[] files = directory.listFiles(new FileFilter() {
			public boolean accept(File file) {
				if (file.getName().startsWith(fn)
						&& file.getName().endsWith(".txt"))
					return true;
				else
					return false;
			}
		});
		if (files.length == 0) {
			System.out.println("No files found. Bye");
			System.exit(0);
		}
		int index = 1;
		for (File f : files) {
			System.out.printf("%d. %s\n", index, f.getName());
			index++;
		}
		System.out.printf("Select solution [1-%d]:", files.length);
		Scanner in = new Scanner(System.in);
		int choice = in.nextInt();
		return files[choice - 1].getAbsolutePath();

	}

	private Solution selectBestSolution(int problemno) {
		String[] p_id = { "solutions//assignment_example_2411.txt",
				"solutions//BestPhaseA//result_a1_1.txt",
				"solutions//BestPhaseA//result_a1_2.txt",
				"solutions//BestPhaseA//result_a1_3.txt",
				"solutions//BestPhaseA//result_a1_4.txt",
				"solutions//BestPhaseA//result_a1_5.txt",
				"solutions//BestPhaseA//result_a2_1.txt",
				"solutions//BestPhaseA//result_a2_2.txt",
				"solutions//BestPhaseA//result_a2_3.txt",
				"solutions//BestPhaseA//result_a2_4.txt",
				"solutions//BestPhaseA//result_a2_5.txt" };
		SolutionImporter solutionImporter2 = new SolutionImporter(problem);
		solutionImporter2.setSolutionFileName(p_id[problemno]);
		Solution solution = solutionImporter2.readData();
		System.out.println();
		return solution;
	}

	@Deprecated
	private void printFeasibilityAndCost(Solution initial_solution,
			Solution new_solution) {
		SolverEnvironment env = new SolverEnvironment(problem,
				initial_solution, new_solution);
		EnhancedCostEvaluator ece = env.getFullValidator();
		ece.computeCost();
		ece.printCostAnalysis();
		if (ece.isFeasible())
			System.out.println("Solution feasible :)");
		else
			System.out.println("Solution infeasible :(");
	}

	private void printFeasibilityAndCost(SolverEnvironment env,
			Solution new_solution) {
		EnhancedCostEvaluator ece = env.getFullValidator();
		ece.computeCost();
		ece.printCostAnalysis();
		if (ece.isFeasible())
			System.out.println("Solution feasible :)");
		else
			System.out.println("Solution infeasible :(");
	}

	private void displayProblems() {
		for (int i = 0; i < datasets.length; i++) {
			System.out.printf("%d. %s %s\n", i, datasets[i],
					initial_solutions[i]);
		}
	}

}